<template>
  <div class="form_item-validate_rule">
    <el-tag class="tag" v-for="(row,i) in this_value" :closable="!is_info" @close="del(i)" :type="row.type">{{ row.content }}</el-tag>

    <template v-if="!is_info">
      <input type="hidden" :name="name" :value="value">

      <div class="flex">
        <select_one :config="select_config" v-model:value="rule_type" style="width: 300px;"></select_one>
        <text_one v-model:value="rule_attr" :placeholder="rule_attr_tips" :config="rule_attr_config" class="max"></text_one>
        <el-button type="primary" @click="add">添加规则</el-button>
      </div>

    </template>
  </div>
</template>

<script>
import select_one from "@/components/auto_import/UnifyParam/select_one.vue";
import text_one from "@/components/auto_import/UnifyParam/text_one.vue";
import {vue_template} from "@/js/dom_tool.js";

export default {
  _title_: '验证规则',
  name: "validate_rule",
  components: {select_one, text_one},

  props: ['name', 'value', 'config', 'is_info', 'size', 'is_list'],
  emits: ['update:value', 'change'],
  data(){
    return {
      need_display: true,
      this_value: [],

      rule_type: '',
      rule_attr: '',
      rule_attr_tips: '',
      rule_attr_config: '',
      rule_map: {
        required: {title:'必填', content:'必填', tips:'无需参数'},
        nullable: {title:'可以为空', content:'可以为空', tips:'无需参数'},

        numeric: {title:'必须为数字', content:'必须为数字', tips:'无需参数'},
        integer: {title:'必须为整数', content:'必须为整数', tips:'无需参数'},
        string: {title:'必须为字符串', content:'必须为字符串', tips:'无需参数'},
        json: {title:'必须为json字符', content:'必须为json字符', tips:'无需参数'},

        in: {title:'在指定列表中', content:'必须在 {{$0}} 之中', must:['限定值'], tips:'请输入限定的值，多个逗号分隔'},
        not_in: {title:'不在指定列表中', content:'必须不在 {{$0}} 之中', must:['限定值'], tips:'请输入限定的值，多个逗号分隔'},

        size: {title:'大小必须等于 $1', content:'大小必须等于{{$1}}', must:['限定值'], tips:'请输入限定的数字(字符数或者数值的值)'},
        min: {title:'大小必须大于或等于 $1', content:'大小必须大于或等于{{$1}}', must:['限定值'], tips:'请输入限定的数字(字符数或者数值的值)'},
        max: {title:'大小必须小于或等于 $1', content:'大小必须小于或等于{{$1}}', must:['限定值'], tips:'请输入限定的数字(字符数或者数值的值)'},

        regex: {title:'必须符合正则规则 $1', content:'必须符合正则规则{{$1}}', must:['正则规则'], tips:'请输入规则表达式，由/开头和结尾'},
        not_regex: {title:'不能符合正则规则 $1', content:'不能符合正则规则{{$1}}', must:['正则规则'], tips:'请输入规则表达式，由/开头和结尾'},

        table_has: {title:'数据表中存在指定数据', content:'数据表{{$1}}存在指定{{$2}}的数据{{$3?("，"+$3+"除外"):""}}', must:['数据表','字段名'], tips:'参数格式：数据表,字段名,忽略值'},
        table_no: {title:'数据表中不存在指定数据', content:'数据表{{$1}}不存在指定{{$2}}的数据{{$3?("，"+$3+"除外"):""}}', must:['数据表','字段名'], tips:'参数格式：数据表,字段名,忽略值'},
      },

    }
  },
  methods: {
    display_value(value){
      if (typeof value == 'string'){
        try {
          value = JSON.parse(value)
        } catch (e) {
          value = [];
        }
      }
      let arr = value ? Object.values(value) : [];
      let res = [];
      arr.forEach((v)=>{
        res.push(this.validate_content(v));
      })
      return res;
    },
    update_value(v){
      this.need_display = false;
      setTimeout(()=>{this.need_display = true;},5);
      this.$emit('update:value', v);
      this.$emit('change', v);
    },
    validate_content(rule_str){
      let res = {content:rule_str, type:'danger', value:rule_str}
      let ms = rule_str.match(/^([^:]+)(:(.+))?$/);
      if (!ms) return res;
      let row = this.rule_map[ms[1]] || "";
      if (row){
        let param = (ms[3] ? ms[3].split(",") : []);
        param.unshift(ms[3]);
        let data = {};
        for (let i = 0; i < 4; i++) {
          data['$'+i] = param[i];
        }
        res.content = vue_template(row.content, data);
      }
      return res;
    },
    del(i){
      this.this_value.splice(i, 1);
      let arr = this.this_value.map((row)=>{
        return row.value;
      })
      this.update_value(JSON.stringify(arr));
    },
    add(){
      if (!this.rule_type) return this.tips("规则类型不能为空！", 3);
      let rule_str = this.rule_type;
      let row = this.rule_map[this.rule_type] || "";
      if (!row) return this.tips("规则类型不存在！", 3);
      if (typeof row.must != "undefined"){
        rule_str += (':'+this.rule_attr);
      }
      // 验证参数是否足够
      let rule_attr_arr = this.rule_attr ? this.rule_attr.split(",") : [];
      let must = row.must || [];
      if (must)
      for (let i = 0; i < must.length; i++) {
        if (!rule_attr_arr[i]) return this.tips(must[i]+" 不能为空！", 3);
      }
      // 修改 this_value 和 value
      this.this_value.push( this.validate_content(rule_str) );
      let arr = this.this_value.map((row)=>{
        return row.value;
      })
      this.update_value(JSON.stringify(arr));
    }
  },
  watch: {
    value(){
      if (!this.need_display) return;
      this.this_value = this.display_value(this.value);
    },
    rule_type(v, oldV){
      this.rule_attr = "";
      this.rule_attr_config = "";
      this.rule_attr_tips = "无需参数";
      let row = this.rule_map[v];
      if (row) this.rule_attr_tips = row.tips;
    }
  },
  computed: {
    select_config(){
      let ks = [];
      if (!this.config) {
        ks = Object.keys(this.rule_map);
      }else {
        ks = this.config.split(",");
      }
      let res = {};
      Object.keys(this.rule_map).forEach((k)=>{
        if (~ks.indexOf(k)) res[k] = this.rule_map[k]['title'];
      })
      return res;
    }
  },
  mounted() {
    this.this_value = this.display_value(this.value)
  }
}
</script>

<style scoped>
.tag{margin: 1px;}
</style>